#pragma once

#include "../Header/Header.h"

//Vector2

class Vector2
{
public:
	//Constructors
	Vector2() : x(0.0f), y(0.0f){}
	Vector2(__float_ _x, __float_ _y) : x(_x), y(_y) {}
	Vector2(__float_ * pArg) : x(pArg[0]), y(pArg[1]) {}
	Vector2(Vector2 & vector) : x(vector.x), y(vector.y) {}

	//Vector's operations
	__float_ Length();
	Vector2 & Normalize();
	Vector2 operator + (Vector2 & vector);
	Vector2 & operator += (Vector2 & vector);
	Vector2 operator - ();
	Vector2 operator - (Vector2 & vector);
	Vector2 & operator -= (Vector2 & vector);
	Vector2 operator * (__float_ k);
	Vector2 & operator *= (__float_ k);
	Vector2 operator / (__float_ k);
	Vector2 & operator /= (__float_ k);
	Vector2 & operator = (Vector2 & vector);
	Vector2 Modulate(Vector2 & vector);
	__float_ Dot(Vector2 & vector);

	//access to elements
	__float_ operator [] (unsigned int idx);

	//data members
	__float_ x;
	__float_ y;
};

//Vector3

class Vector3
{
public:
	//Constructors
	Vector3() : x(0.0f), y(0.0f), z(0.0f) {}
	Vector3(__float_ _x, __float_ _y, __float_ _z) : x(_x), y(_y), z(_z) {}
	Vector3(__float_ * pArg) : x(pArg[0]), y(pArg[1]), z(pArg[2]) {}
	Vector3(Vector3 & vector) : x(vector.x), y(vector.y), z(vector.z) {}
	
	//Vector's operations
	__float_ Length();
	Vector3 & Normalize();
	Vector3 operator + (Vector3 & vector);
	Vector3 & operator += (Vector3 & vector);
	Vector3 operator - ();
	Vector3 operator - (Vector3 & vector);
	Vector3 & operator -= (Vector3 & vector);
	Vector3 operator * (__float_ k);
	Vector3 & operator *= (__float_ k);
	Vector3 operator / (__float_ k);
	Vector3 & operator /= (__float_ k);
	Vector3 & operator = (Vector3 & vector);
	Vector3 Modulate(Vector3 & vector);
	__float_ Dot(Vector3 & vector);
	Vector3 Cross(Vector3 & vector);

	//access to elements
	__float_ operator [] (unsigned int idx);

	// data members
	__float_ x;
	__float_ y;
	__float_ z;
};

//Vector4

class Matrix;

class Vector4
{
public:
	//Constructors
	Vector4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
	Vector4(__float_ _x, __float_ _y, __float_ _z) : x(_x), y(_y), z(_z), w(1.0f) {}
	Vector4(__float_ _x, __float_ _y, __float_ _z, __float_ _w) : x(_x), y(_y), z(_z), w(_w) {}
	Vector4(__float_ * pArg) : x(pArg[0]), y(pArg[1]), z(pArg[2]), w(pArg[3]) {}
	Vector4(Vector3 & vector) : x(vector.x), y(vector.y), z(vector.z), w(1.0f){}
	Vector4(Vector3 & vector, __float_ _w) : x(vector.x), y(vector.y), z(vector.z), w(_w) {}
	Vector4(Vector4 & vector) : x(vector.x), y(vector.y), z(vector.z), w(vector.w) {}

	//Vector's operations
	__float_ Length();
	Vector4 & Normalize();
	Vector4 operator + (Vector4 & vector);
	Vector4 & operator += (Vector4 & vector);
	Vector4 operator - ();
	Vector4 operator - (Vector4 & vector);
	Vector4 & operator -= (Vector4 & vector);
	Vector4 operator * (__float_ k);
	Vector4 & operator *= (__float_ k);
	Vector4 operator / (__float_ k);
	Vector4 & operator /= (__float_ k);
	Vector4 & operator = (Vector4 & vector);
	Vector4 Modulate(Vector4 & vector);
	__float_ Dot(Vector4 & vector);

	//matrix multiplication
	Vector4 operator * ( Matrix & m );

	//access to elements
	__float_ operator [] (unsigned int idx);

	//data members
	__float_ x;
	__float_ y;
	__float_ z;
	__float_ w;
};

//Matrix 4 X 4


class Matrix
{
public:
	//constructors
	Matrix() {}
	Matrix(__float_ val);
	Matrix(Matrix & mat);

	// Matrix operations
	Matrix & SetZero();
	Matrix & SetIdentity();

	Matrix & SetRotationX(__float_ angle);
	Matrix & SetRotationY(__float_ angle);
	Matrix & SetRotationZ(__float_ angle);
	Matrix & SetRotationAngleAxis( float angle, float x, float y, float z );

	Matrix & SetScale(__float_ scale);
	Matrix & SetScale(__float_ scaleX, __float_ scaleY, __float_ scaleZ);
	Matrix & SetScale(__float_ * pScale);
	Matrix & SetScale(Vector3 &scaleVec);

	Matrix & SetTranslation(__float_ x, __float_ y, __float_ z);
	Matrix & SetTranslation(__float_ *pTrans);
	Matrix & SetTranslation(Vector3 &vec);

	Matrix & SetPerspective(__float_ fovY, __float_ aspect, __float_ nearPlane, __float_ farPlane);

	Matrix Transpose();

	Matrix operator + (Matrix & mat);
	Matrix & operator += (Matrix & mat);
	Matrix operator - (Matrix & mat);
	Matrix &operator -= (Matrix & mat);

	Matrix operator * (Matrix & mat);
	Matrix operator * (__float_ k);
	Matrix & operator *= (__float_ k);

	Vector4 operator * (Vector4 & vec);

	Matrix & operator = (Matrix & mat);

	//data members
	__float_ m[4][4];
};
